#pragma once

#include <iosfwd>
#include <exception>
#include <string>
#include <sstream>
#include "ckr_spec_Context.h"

namespace  ckr
{

template < typename Container >
class AssertableContainer
{
public:
	typedef typename Container::value_type		value_type;

	const Container&			container;
	Context&						caller;
	const char*					containerAsString;
	int							lineNumber;
	const char*					srcFileName;

	AssertableContainer(	const Container&		containerIn,
							const char*					containerAsStringIn,
							Context&						callerIn,
							int							lineNumberIn,
							const char*					srcFileNameIn )
		: container( containerIn )
		, caller( callerIn )
		, containerAsString( containerAsStringIn )
		, lineNumber( lineNumberIn )
		, srcFileName( srcFileNameIn )
	{
	}

	void should_equal_impl( const Container& other, const char* otherName )
		// use SHOULD_CONTAIN instead of calling this directly.
	{
		if ( not ( container == other ) )
		{
			report_failure_operation( otherName, "should equal" );
		}
	}

	void should_contain_impl( const value_type& other, const char* otherName )
		// use SHOULD_CONTAIN instead of calling this directly.
	{
		if ( container.end() == std::find( container.begin(), container.end(), other ) )
		{
			report_failure_operation( other, otherName, "should contain" );
		}
	}

	void should_not_contain_impl( const value_type& other, const char* otherName )
		// use SHOULD_NOT_CONTAIN instead of calling this directly.
	{
		if ( container.end() != std::find( container.begin(), container.end(), other ) )
		{
			report_failure_operation( other, otherName, "should not contain" );
		}
	}

	void report_failure_operation( const value_type& other, const char* otherName, 
			const char* operation_name )
	{
		std::stringstream strm;
		strm << containerAsString 
			<< " "
			<< operation_name
			<< " "
			<< otherName
			<< " ("
			<< other
			<< ")";

		caller.fail_impl( strm.str(), lineNumber, srcFileName );
	}

	void report_failure_operation( const char* otherName, 
			const char* operation_name )
	{
		std::stringstream strm;
		strm << containerAsString 
			<< " "
			<< operation_name
			<< " "
			<< otherName;

		caller.fail_impl( strm.str(), lineNumber, srcFileName );
	}
};


}; // end namespace

